package com.lhweb.springsecurity.security;

import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.userdetails.UserDetails;

/**
 * 自定义的Provider 自定义的过滤器最终将请求指向AuthenticationManager，
 * 所以需自定义AuthenticationProvider来处理验证自定的provider 这里我们扩展spring
 * security的DaoAuthenticationProvider来实现
 * 
 *当配置了多个AuthenticationProvider时，每个AuthenticationProvider都会检查
 *过滤器提供给它的AuthenticationToken,仅当这个token类型它支持时才会处理 
 *
 * @author liuhuan 2015年1月13日 下午2:24:31
 */
public class SignedUsernamePasswordAuthenticationProvider extends
		DaoAuthenticationProvider {

	//向AuthenticationManager指明当前AuthenticationProvider
	//要进行校验的期望运行时Authentication token
	@Override
	public boolean supports(Class<? extends Object> authentication) {
		return SignedUsernamePasswordAuthenticationToken.class
				.isAssignableFrom(authentication);
	}

	/**
	 * 允许子类对token进行特有的校验
	 */
	@Override
	protected void additionalAuthenticationChecks(UserDetails userDetails,
			UsernamePasswordAuthenticationToken authentication) {
		super.additionalAuthenticationChecks(userDetails, authentication);
		SignedUsernamePasswordAuthenticationToken signedToken = (SignedUsernamePasswordAuthenticationToken) authentication;
		//signature 为空
		if(signedToken.getRequestSignature()==null){
			throw new BadCredentialsException(messages.getMessage("Missing request signature"));
		}
		//
		if(!signedToken.getRequestSignature().equals(calculateExpectedSignature(signedToken))){
			throw new BadCredentialsException(messages.getMessage("Invalid request signature"));
		}
	}

	private Object calculateExpectedSignature(
			SignedUsernamePasswordAuthenticationToken signedToken) {
		return signedToken.getPrincipal()+"|+|"+signedToken.getCredentials();
	}
}
